﻿<!DOCTYPE html>
<html>
    <head>
        <title>My Map</title>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        <meta charset="utf-8">

        <link href="/maps/documentation/javascript/examples/default.css" rel="stylesheet">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script>
        <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&amp;sensor=false&amp;key=AIzaSyBU7QKmIDolsy8AgZoP57vf9EhY-Eore0w" type="text/javascript"></script>
        <script type="text/javascript">


            /**
             * GStreetviewPanorama of the Flash viewer.
             */
            var pano;

            /**
             * GStreetviewClient used to retrieve meta data for panoramas we reach
             * by following links.
             */
            var svClient;


            /**
             * The GRoute we are following extracted from the directions response.
             */
            var route;

            /**
             * It turns out that the polyline generated for a driving directions
             * route normally has a lot of repeated vertices. This causes problems
             * when trying to determine how close we are to the next vertex, so it's
             * better to collapse these duplicated vertices out.
             *
             * The array of route vertices with duplicates removed.
             */
            var vertices;

            /**
             * Array that maps the polyline vertex indices to the
             * index of the same point in the vertices array.
             *
             * For example, if the polyline vertices are
             * [a, a, b, c, d, d, e], the vertices array will be
             * [ a, b, c, d, e ] and the vertexMap array will be
             * [ 1, 1, 2, 3, 4, 4, 5 ].
             */
            var vertexMap;

            /**
             * Array that contains the index in the vertices array of
             * the point at the start of the n'th step in the route
             */
            var stepToVertex;

            /**
             * An array that gives the route step number that each
             * point in the vertices array is part of.
             */
            var stepMap;

            /**
             * The current position of the panorama and vehicle marker.
             */
            var currentLatLng;

            /**
             * Metadata for the current panorama including the list of
             * available links, loaded using GStreetviewClient.
             */
            var panoMetaData;

            /**
             * boolean flag set when we are so close to the next vertex that we should
             * check links in the panoramas we load for the next turning we need.
             */
            var close = false;

            /**
             * The direction in degrees from our current location to the next
             * vertex on the route. Used to select the most suitable link to follow.
             */
            var bearing;

            /**
             * The direction from the next vertex on the route to the vertex
             * after that. Used when we are close to a vertex and are looking
             * for links that represent the next turn we need to make.
             */
            var nextBearing;

            /**
             * The index of the vertex we are heading towards on the route in the
             * vertices array.
             */
            var nextVertexId;

            /**
             * GLatLng of the vertex we are heading towards on the route.
             */
            var nextVertex;

            /**
             * An array that at any time contains the GLatLng of each vertex
             * from the start of the current route step to the next vertex
             * ahead of our current position. This is used to work out how
             * far we are along the current step.
             */
            var progressArray;

            /**
             * The distance in meters covered by traversing the points in the
             * progressArray. By subtracting the distance from our current location
             * to the next vertex from this value we find how far along the step
             * we are, and use this to update the progress bar.
             */
            var progressDistance;

            /**
             * Index of the route step we are currently on.
             */
            var currentStep;

            /**
             * The marker on our map that shows the current location. For IE6 this
             * is a standard red maps pushpin. For all other browsers it is a
             * directional arrow.
             */
            var carMarker;

            /**
             * A copy of the current step index used to unhighlight the previously
             * highlighted step in the textual driving directions when the
             * current step changes.
             */
            var selectedStep = null;

            /**
             * boolean flag indicating whether we are currently driving (automatically
             * following) links, or are stationary.
             */
            var driving = false;

            /**
             * Id of the timer that adds a delay between following each link to give the
             * panorama time to load. We need this to cancel the timer if the user clicks
             * Stop while we are waiting to follow the next link.
             */
            var advanceTimer = null;

            /**
             * Delay in seconds between following each link.
             */
            var advanceDelay = 1;

            var sv = new google.maps.StreetViewService();
            var directionsDisplay;
            var directionsService = new google.maps.DirectionsService();
            var map;

            var polyline;

            var walkstepindex;
            var walking = false;
            var walklastpano;
            
            var debugmsgarr=new Array();
            var showdebugmsg=false;
            
            var lastll;
            var steps;

            google.maps.event.addDomListener(window, 'load', initialize);



            function initialize() {
                hideStatus();

                polyline = new google.maps.Polyline({
                    path: [],
                    strokeColor: '#0000FF',
                    strokeWeight: 5
                });

                directionsDisplay = new google.maps.DirectionsRenderer();

                var sthere = new google.maps.LatLng(24.996749, 121.544714);

                var mapOptions = {
                    zoom: 15,
                  /*  center: sthere, */
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };
                map = new google.maps.Map(document.getElementById('map-canvas'),
                        mapOptions);
                directionsDisplay.setMap(map);

                directionsDisplay.setPanel(document.getElementById('directions-panel'));

                //street view from here 

                carMarker = getCarMarker(sthere);
                //map.addOverlay(carMarker);
                carMarker.setVisible(true);
                bearing = 0;
                var panoramaOptions = {
                    position: sthere,
                    pov: {
                        heading: bearing,
                        pitch: 10
                    },
                    zoomControl: true
                };
                pano = new google.maps.StreetViewPanorama(document.getElementById('streeview-canvas'), panoramaOptions);
                map.setStreetView(pano);
                pano.setVisible(false);
                pano.setZoom(0);


                google.maps.event.addDomListener(pano, "initialized", function(loc) {
                    panoMetaData = loc;
                    moveCar();
                });

                google.maps.event.addListener(pano, "position_changed", function() {
                    if (walking) {
                        map.panTo(pano.getPosition());
                        advanceTimer = setTimeout('stepRouteNext()', advanceDelay * 1000);
                    }
                });
                
                google.maps.event.addDomListener(directionsDisplay, "directions_changed", function() {
                    jumpInMyCar();
                });

                var url=window.location.toString(); //取得當前網址
                var str=""; //參數中等號左邊的值
                var str_value=""; //參數中等號右邊的值
                var autostart=false;
                var wp=1;
                if(url.indexOf("?")!==-1){
                    //如果網址有"?"符號
                    var ary=url.split("?")[1].split("&");
                    //取得"?"右邊網址後利用"&"分割字串存入ary陣列 ["a=1","b=2","c=3"]
                    for(var i in ary){
                        //取得陣列長度去跑迴圈，如:網址有三個參數，則會跑三次
                        str=ary[i].split("=")[0];
                        //取得參數"="左邊的值存入str變數中
                        if (str === "From") {
                        //若str等於想要抓取參數 如:b
                            document.getElementById('start').value = decodeURI(ary[i].split("=")[1]);
                            //取得b等號右邊的值並經過中文轉碼後存入str_value
                        }
                        if (str === "To") {
                            document.getElementById('end').value = decodeURI(ary[i].split("=")[1]);
                        }
                        if (str === "DriveWay") {
                            var _driveway = decodeURI(ary[i].split("=")[1]);
                            document.getElementById('mode').value = _driveway;
                        }
                        if (str === "WayPoint") {
                            var _waypoint = decodeURI(ary[i].split("=")[1]);
                            document.getElementById('w' + wp.toString().trim() ).value = _waypoint;
                            wp +=1 ;
                        }
                        if (str === "AutoStart") {
                            autostart=true;
                        }
                    }
                    showDebugmsg('wp=' + wp.toString().trim() + ';' );
                    if(autostart){
                        showDebugmsg('自動啟動!!');
                        calcRoute();
                        advanceTimer = setTimeout('startDriving()',  10000);
                    }
                }


                /* 自動執行加速測試 */
                /*
                 showDebugmsg('測試go!!');
                 calcRoute();
                 stepRouteStart();
                 */
            }

            /* 開始走每一點 */
            function stepRouteStart() {
                debugmsgarr=new Array();
                steps=new Array();
                showDebugmsg('stepRouteStart go!!');
                //walkstepindex = 0;
                walking = true;
                //markAllVertice();
                if(walkstepindex===0){
                    map.setZoom(16);
                    checkCoverage(0);
                    pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                }
                setTimeout('stepRouteNext()', 0);
            }

            function stepRouteStop() {
                //showDebugmsg('stepRouteStop!!');
                walking = false;
                if (advanceTimer !== null) {
                    clearTimeout(advanceTimer);
                    advanceTimer = null;
                }
            }

            function markAllVertice(){
                for(var v=0;v < vertices.length;v++){
                    var marker = getCarMarker(vertices[v]);
                    marker.setVisible(true);
                }
            }

            function stepRouteNext() {

                /* 先停止timer */
                if (advanceTimer !== null) {
                    clearTimeout(advanceTimer);
                    advanceTimer = null;
                }
                 
                var aa = 0;
             
                //showDebugmsg('step  '  +  (aa++).toString() );  

                showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 進入點 ->  pano.getposition=' + pano.getPosition().toString() + ', 方位角=' + pano.getPov().heading.toString() );  
        
                var nowl = pano.getPosition();
                var nextv = vertices[walkstepindex];
                var lastv = vertices[(walkstepindex===0?0:walkstepindex-1)];
                var dist = google.maps.geometry.spherical.computeDistanceBetween(nowl, nextv);
                var dist2v = google.maps.geometry.spherical.computeDistanceBetween(lastv, nextv);
                var dist1v = google.maps.geometry.spherical.computeDistanceBetween(nowl, lastv);

                 var instep =   steps.indexOf(nowl.toString(),0);

                 if(instep===-1){
                     steps.push(nowl.toString());
                 }

                /* 已經到下一個頂點 往下一個頂點轉向 */
                if(dist<5){
                    walkstepindex +=1;
                    nextv = vertices[walkstepindex];
                    lastv = vertices[(walkstepindex===0?0:walkstepindex-1)];
                    dist = google.maps.geometry.spherical.computeDistanceBetween(nowl, nextv);
                    dist2v = google.maps.geometry.spherical.computeDistanceBetween(lastv, nextv);
                    dist1v = google.maps.geometry.spherical.computeDistanceBetween(nowl, lastv);
                    walklastpano = undefined;
                }

                showDebugmsg('dist(nowl, nextv)= ' + dist.toFixed(4).toString() + ' , dist2v(lastv, nextv)=' + dist2v.toFixed(4).toString() + ' ,dist1v(nowl, lastv)=' + dist1v.toFixed(4).toString() );  

                //showDebugmsg('step  '  +  (aa++).toString() );  

               /* 只跑頂點 */
                var onlyvertics = false;
                if (onlyvertics) {
                    walkstepindex += 1;
                    nextv = vertices[walkstepindex];
                    nextBearing = getBearing(vertices[walkstepindex - 1], vertices[walkstepindex]);
                    bearing = nextBearing;
                    lastll=pano.getPosition();
                    pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                    //sv.getPanoramaByLocation(lastv, 5, processSVData);
                    pano.setPosition(lastv);
                    if (walkstepindex >= vertices.length) {
                        stopDriving();
                    }
                    showDebugmsg('only Vertice  -> ' + walkstepindex.toString() + '/' + vertices.length.toString() + '<>' + bearing.toString());
                    return;
                }

               //showDebugmsg('step  '  +  (aa++).toString() );  

                /* 距離下個頂點不到10米,直接走到頂點,設定下個頂點為目標 */
                if (dist <= 10 ) {
                    lastll=pano.getPosition();
                    //pano.setPosition(nextv);
                    walkstepindex += 1;
                    walklastpano = undefined;
                    checkCoverage(walkstepindex);
                    if (walkstepindex >= vertices.length) {
                        stopDriving();
                    }
                    showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 到達頂點 ->  location=' + nextv.toString() + ', 新方位角=' + getBearing(nowl, vertices[walkstepindex]).toString() + ', 距離頂點='  + dist.toString() );  
                    //advanceTimer = setTimeout('stepRouteNext()', 1 * 1000);
                    return;
                }
                
                //showDebugmsg('step  '  +  (aa++).toString() );  

                 /* 計算方位角, 目前方向大於45度就先轉向, 再往前走 */
                bearing = getBearing(nowl, vertices[walkstepindex]);
                if (walkstepindex ===  0) {
                    nextBearing = getBearing(vertices[0], vertices[1]);
                } else {
                    nextBearing = getBearing(vertices[walkstepindex -1], vertices[walkstepindex]);
                }

                //showDebugmsg('step  '  +  (aa++).toString() );  
                showDebugmsg('bearing=' + bearing.toString() +  ', nextBearing=' + nextBearing.toString() );

                d1 = Math.abs(pano.getPov().heading - bearing);
                d1 = Math.abs((Math.floor(d1 / 180) * 360) - d1);
                if (d1 > 45) {
                    showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 轉動視線朝前進方向 ->  location=' + nowl.toString() + ', 前進方位角=' + bearing.toString() + ', 視線方位角='  + pano.getPov().heading.toString() + ', 差角=' + d1.toString() );  
                    if (d1 > 60) {
                        d2 = (bearing - pano.getPov().heading + 360 ) % 360 ;
                        d2 = Math.round(((d2 % 180) - (Math.floor(d2/180) * 180)) / 2 ,0) ;
                        var newbearing= (pano.getPov().heading + d2 + 360) % 360;
                        if((newbearing<0) || (newbearing>360)){
                            if (newbearing < 0 ) {newbearing += 360;}
                            if (newbearing > 360 ) {newbearing -= 360;}
                        }
                        pano.setPov({heading: newbearing, pitch: pano.getPov().pitch});
                        //pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                        showDebugmsg('newbearing=' + newbearing.toString() + ', d2=' + d2.toString() );
                    } else {
                        pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                    }
                    advanceTimer = setTimeout('stepRouteNext()', advanceDelay * 1000);
                    return;
                }
                
        //showDebugmsg('step  '  +  (aa++).toString() );  


               /* 往前走, 取得下一個link */
                var svlinks = pano.getLinks();
                var nextp = svlinks[0];
                var alllinks = svlinks[0].heading.toString();
                for (var lnk = 1; lnk < svlinks.length; lnk++) {
                    d1 = Math.abs(svlinks[lnk].heading - bearing);
                    d2 = Math.abs(nextp.heading - bearing);
                    d1 = Math.abs((Math.floor(d1 / 180) * 360) - d1);
                    d2 = Math.abs((Math.floor(d2 / 180) * 360) - d2);
                    if(lnk===1){
                        alllinks +=   '(' + d2.toString() + ')' ;
                    }
                    alllinks += ' ; ' + svlinks[lnk].heading.toString() + '(' + d1.toString() + ')' ;
                    if (d1 < d2) {
                        nextp = svlinks[lnk];
                    }
                }

                showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 全部link -> ' + alllinks + ', 下個前進方位角=' + nextp.heading.toString() + ' ,前進方向=' + nextBearing.toString() );  
        
                /* 超過40度表示無路可走  */
                d2 = Math.abs(nextp.heading - bearing);
                d2 = Math.abs((Math.floor(d2 / 180) * 360) - d2);
                if (d2>40){
                    lastll=pano.getPosition();
                    walkstepindex += 1;
                    walklastpano = undefined;
                    checkCoverage(walkstepindex);
                    if (walkstepindex >= vertices.length) {
                        stopDriving();
                    }
                    showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 超過40度的差異無路可走,直接到下個頂點 ->  location=' + nextv.toString() + ', 新方位角=' + getBearing(nowl, vertices[walkstepindex]).toString() + ', 距離頂點='  + dist.toString() );  
                    //advanceTimer = setTimeout('stepRouteNext()', 1 * 1000);
                    return;
                }
        
                /* 下一個link, 已經走過, 直接到下個頂點 !(walklastpano === undefined)  && (dist1v > 10) */
                if (!(walklastpano === undefined) && (dist1v > 10) ) {
                    d1 = Math.abs(nextp.heading  -  walklastpano.heading);
                    d1 = Math.abs((Math.floor(d1 / 180) * 360) - d1);
                    // nextp.pano == walklastpano.pano || 
                    if ( ( (d1 > 170) && (d1 < 190)) ) {
                        lastll=pano.getPosition();
                        //bearing = getBearing(nowl, nextv);
                        //nextv = google.maps.geometry.spherical.computeOffset(nowl, 15, bearing, 20);
                        //pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                        //sv.getPanoramaByLocation(nextv, 20, processSVData);
                       //pano.setPosition(nextv);
                        showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 下個link已經走過 ->  location=' + nowl.toString() + ', 前進方位角=' + nextp.heading.toString() + ', 前一個前進方位角='  + walklastpano.heading.toString() + ', 差角=' + d1.toString() );  
                        nextv = google.maps.geometry.spherical.computeOffset(nowl, 15, bearing, 20);
                        //nextv = google.maps.geometry.spherical.computeOffsetOrigin(nowl, 15, nextBearing, 20);
                        walkstepindex += 1;
                        walklastpano = undefined;
                        checkCoverage(walkstepindex);
                        return;
                    }
                }
                   
                //showDebugmsg('step  '  +  (aa++).toString() );  
                 /* 下一個link跟目前方向大於85度, 先調整方向 */  

                /*
                d2 = Math.abs(nextp.heading - bearing);
                d2 = Math.abs((Math.floor(d2 / 180) * 360) - d2);

                if (d2 > 85) {
                    showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 下個link超過85度 ->  location=' + nowl.toString() + ', 前進方位角=' + nextp.heading.toString() + ', 應前進方位角='  + bearing.toString() + ', 差角=' + d2.toString() );  
                    lastll=pano.getPosition();
                    bearing = getBearing(nowl, nextv);
                    nextv = google.maps.geometry.spherical.computeOffset(nowl, 15, bearing, 20);
                    pano.setPov({heading: bearing, pitch: pano.getPov().pitch});
                    //sv.getPanoramaByLocation(nextv, 20, processSVData);
                    pano.setPosition(nextv);
                    //stopDriving();
                    return;
                }
                */
                //showDebugmsg('step  '  +  (aa++).toString() );  

/*
                if (nextBearing != bearing) {
                    bearing = nextBearing;
                }
*/        

                /* 往前走一個link */ 

                lastll=pano.getPosition();
                pano.setPov({heading: nextp.heading, pitch: pano.getPov().pitch});
                pano.setPano(nextp.pano);
                walklastpano = nextp;
                showDebugmsg('( ' + walkstepindex.toString() + '/' + vertices.length.toString() + ') 往下個link ->  location=' + nowl.toString() + ', 下個location'  + pano.getPosition().toString() +  ', 前進方位角=' + nextp.heading.toString()  );  
                //sv.getPanoramaByLocation(nextv, 20, processSVData);

                if (walkstepindex >= vertices.length) {
                    stopDriving();
                }

                /*
                 showDebugmsg('stepRouteNext Go ' + (walkstepindex+1).toString() + '/' + vertices.length.toString() + ' , ' 
                 + ' (' + bearing.toString() + ') ' 
                 + dist.toString() );
                 */

            }

            /* 路徑規劃 */
            function calcRoute() {
                var selectedMode = document.getElementById("mode").value;
                var start = document.getElementById('start').value;
                var end = document.getElementById('end').value;
                var wayps = new Array();
                for(var i=1; i<= 8 ;i++ ){
                    var wayp = document.getElementById('w' + i.toString().trim() ).value;
                    if(wayp!==''){
                        wayps.push({location:wayp, stopover:true});
                    }
                }
                var request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode[selectedMode],
                    waypoints: wayps
                };
                directionsService.route(request, function(response, status) {
                    if (status == google.maps.DirectionsStatus.OK) {
                        /*
                         path = response.routes[0].overview_path;
                         $(path).each(function(index, item) {
                         polyline.getPath().push(item);
                         })
                         */
                        directionsDisplay.setDirections(response);
                        walkstepindex = 0;
                    }
                });
            }

            function setSpeed() {
                advanceDelay = document.getElementById('speed').selectedIndex;
            }


            /**
             * It's too far to walk on your own
             */
            function jumpInMyCar() {
                /* Extract the one and only route from this response */
                route = directionsDisplay.getDirections().routes[0]

                /* Simplify the list of polyline vertices by removing duplicates */
                collapseVertices();

                /* Center the map on the start of the route at street level */
                map.setCenter(vertices[0]);

                /* Display the textual driving directions */
                //renderTextDirections();

                /* Begin checking the Street View coverage along this route */
                checkCoverage(0);

                bearing = getBearing(vertices[0], vertices[1]);
                pano.setPov({heading: bearing, pitch: pano.getPov().pitch});

            }

            /**
             * Build the vertices, vertexMap, stepToVertex, and stepMap
             * arrays from the vertices of the route polyline.
             * @param {GPolyline} path The route polyline to process
             */
            function collapseVertices() {
                showDebugmsg('collapseVertices');
                vertices = new Array();
                vertices.push(route.legs[0].start_location);
                for (var l = 0; l < route.legs.length; l++) {
                    if (!(route.legs[l].steps === undefined)) {
                        retriveSteps(route.legs[l].steps);
                    } else {
                        var lstvertice = vertices[vertices.length - 1];
                        if (!route.legs[l].start_location.equals(lstvertice)) {
                            vertices.push(route.legs[l].start_location);
                        }
                        vertices.push(route.legs[l].end_location);
                    }
                }
            }

            function retriveSteps(isteps) {
                for (var s = 0; s < isteps.length; s++) {
                    for (var p = 0; p < isteps[s].path.length; p++) {
                        var lstvertice = vertices[vertices.length - 1];
                        if (!isteps[s].path[p].equals(lstvertice)) {
                            vertices.push(isteps[s].path[p]);
                        }
                    }
                }
            }


            /**
             * Check that a Street View panorama exists at the start
             * of this route step. This is a recursive function that
             * checks every step along the route until it reaches the
             * end of the route or no panorama is found for a step.
             * @param {number} step The route step to check
             */
            function checkCoverage(step) {
                var ll = vertices[step];
                sv.getPanoramaByLocation(ll, 20, processSVData);
            }


            function processSVData(data, status) {
                if (status === google.maps.StreetViewStatus.OK) {
                    var markerPanoID = data.location.pano;
                    // Set the Pano to use the passed panoID
                    pano.setPano(markerPanoID);
                    if(walkstepindex < vertices.length){
                         if(walkstepindex === 0) {
                             pano.setPov({heading: getBearing(data.location.latLng , vertices[walkstepindex+1]) , pitch:  pano.getPov().pitch });
                         }else{
                             pano.setPov({heading: getBearing(vertices[walkstepindex] , vertices[walkstepindex+1]) , pitch:  pano.getPov().pitch });
                         }
                    }
                    pano.setVisible(true);
                    if(walking){
                        advanceTimer = setTimeout('stepRouteNext()' ,  advanceDelay * 1000); 
                    }
                }else{
                    walkstepindex+=1;
                    advanceTimer = setTimeout('checkCoverage(' + walkstepindex.toString() + ')' ,  10); 
                }
            }



            /**
             * Called by the panorama's initialized event handler in
             * response to a link being followed. Updates the location
             * of the vehicle marker and the center of the map to match
             * the location of the panorama loaded by following the link.
             */
            function moveCar() {
                currentLatLng = panoMetaData.latlng;
                carMarker.setVisible(true);
                carMarker.setPosition(currentLatLng);
            }

            /**
             * Create a vehicle marker suited to the user's browser
             * Avoids a wierd IE6 bug that causes black backgrounds
             * if we use the driving direction arrows as marker icons
             * @param {GLatLng} start Initial location of the vehicle marker
             * @return {GMarker}
             */
            function getCarMarker(start) {
                var markOptions = {
                    position: start,
                    //icon: getArrowIcon(0.0),
                    map: map,
                    title: '現在位置'
                };
                return new google.maps.Marker(markOptions);
            }

            /**
             * Set the vehicle marker icon based on the user's browser
             * Avoids a wierd IE6 bug that causes black backgrounds
             * if we use the driving direction arrows as marker icons
             * @param {number} bearing The heading in degrees of the arrow we need
             */
            function setCarMarkerImage(bearing) {
                /*@cc_on @*/
                /*@if (@_jscript_version < 5.7)
                 return;
                 /*@end @*/
                carMarker.setImage(getArrowUrl(bearing));
            }

            /**
             * Generate a GMarker icon of an direction arrow
             * @param {number} bearing Direction arrow should point
             * @return {GIcon}
             */
            function getArrowIcon(bearing) {
                var iconOptions = {
                    URL: 'http://www.google.com.tw/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&docid=N_Ung8zZzNcReM&tbnid=AQXr5kZKy0Zm7M:&ved=&url=http%3A%2F%2Fwww.easyicon.net%2Flanguage.en%2Ficondetail%2F548226%2F&ei=Ty3AUeeyMIXckgWIi4CgDA&psig=AFQjCNHbXv9LtdQddo1uSgaXDbPXEZAfRQ&ust=1371635408427028',
                    size: new google.maps.Size(24, 24, 'px', 'px'),
                    anchor: new google.maps.Point(12, 12),
                    origin: new google.maps.Point(0, 0)
                };
                var icon = new google.maps.Icon(iconOptions);
                return icon;
            }

            /**
             * Determine URL of correct direction arrow image to use
             * @param {number} bearing Direction arrow should point
             * @return {String}
             */
            function getArrowUrl(bearing) {
                var id = (3 * Math.round(bearing / 3)) % 120;
                return "http://maps.google.com/mapfiles/dir_" + id + ".png";
            }


            /**
             * Update the UI for driving and start following links
             */
            function startDriving() {
                hideInstruction();
                document.getElementById("route").disabled = true;
                document.getElementById("stopgo").value = "Stop";
                document.getElementById("stopgo").setAttribute('onclick', 'stopDriving()');
                document.getElementById("stopgo").onclick = function() {
                    stopDriving();
                }
                driving = true;
                stepRouteStart();
            }

            /**
             * Stop following links and update the UI
             */
            function stopDriving() {
                driving = false;

                if (advanceTimer != null) {
                    clearTimeout(advanceTimer);
                    advanceTimer = null;
                }

                document.getElementById("route").disabled = false;
                document.getElementById("stopgo").disabled = false;
                document.getElementById("stopgo").value = "Drive";
                document.getElementById("stopgo").setAttribute('onclick', 'startDriving()');
                document.getElementById("stopgo").onclick = function() {
                    startDriving();
                }
                showInstruction('Press <b>Drive</b> to follow your route');
                stepRouteStop();
            }


            function SvMax() {
                document.getElementById("svzoom").value = '縮小';
                document.getElementById("svzoom").setAttribute('onclick', 'SvMin()');
                document.getElementById("svzoom").onclick = function() {
                    SvMin();
                }
                document.getElementById("svpanel").setAttribute('style', 'height: 90%;');
            }

            function SvMin() {
                document.getElementById("svzoom").value = '放大';
                document.getElementById("svzoom").setAttribute('onclick', 'SvMax()');
                document.getElementById("svzoom").onclick = function() {
                    SvMax();
                };
                document.getElementById("svpanel").setAttribute('style', 'height: 45%;');
            }

            //---------------------------------

            function showDebugmsg(message)
            {
                document.getElementById("debugmsg").innerHTML = message;
                if(showdebugmsg){
                    debugmsgarr.unshift(message);
                    if(debugmsgarr.length > 30){ 
                        debugmsgarr.pop();
                    }
                     var msgs = '';
                     for (var i=0; i<debugmsgarr.length;i++)
                     {
                         msgs += debugmsgarr[i] + '<br/>' ;
                     }
                    document.getElementById("directions-panel").style.display = "none";
                    document.getElementById("debugmsg-panel").style.display = "block";
                    document.getElementById("debugmsg-panel").innerHTML = msgs;
                }
            }

            /**
             * Display a status message that fills the Flash viewer
             * @param {String} message The message to display
             */
            function showStatus(message) {
                hideInstruction();
                document.getElementById("status").innerHTML = message;
                document.getElementById("status").style.display = "block";
                document.getElementById("streeview-canvas").style.display = "none";
            }

            /**
             * Hide the currently displayed status message
             */
            function hideStatus() {
                document.getElementById("status").style.display = "none";
                document.getElementById("streeview-canvas").style.display = "block";
            }

            /**
             * Display an instructional message at the bottom of the Flash viewer
             * @param {String} message The message to display
             */
            function showInstruction(message) {
                document.getElementById("instruction").innerHTML = message;
                document.getElementById("instruction").style.display = "block";
            }

            /**
             * Hide the currently displayed instructional message
             */
            function hideInstruction() {
                document.getElementById("instruction").style.display = "none";
            }


            /* Following functions based on those provided at:
             * http://www.movable-type.co.uk/scripts/latlong.html
             * Copyright 2002-2008 Chris Veness
             */

            /**
             * Calculate the bearing in degrees between two points
             * @param {number} origin      GLatLng of current location
             * @param {number} destination GLatLng of destination
             * @return {number}
             */
            function getBearing(origin, destination) {
                if (origin.equals(destination)) {
                    return null;
                }
                var ret = (360 + google.maps.geometry.spherical.computeHeading(origin, destination)) % 360;
                return Math.round(ret, 0);
            }


        </script>
        <style type="text/css">
            html { height: 100%; }
            body { height: 100%; margin: 0; padding: 0; }
            #svpanel {height: 45%; border: 1px solid gray;}
            #streeview-canvas {height: 100%;}

            #map-canvas { height: 45%; margin-right: 400px; border: 1px solid gray;}
            #directions-panel { height: 45%; float: right; width: 390px; overflow: auto;  border: 1px solid gray;}
            #debugmsg-panel { height: 45%; float: right; width: 390px; overflow: auto;  border: 1px solid gray; display:none; }

            #controls {height: 10%; width: 100%; border: 1px solid gray;}
            #SEinput { height: 100%; width: 100%; border: 1px solid gray;}
            #buttons { height: 100%; width: 100%; border: 1px solid gray;}

            #status {
                height: 100%;
                text-align: center;
                font: 32pt sans-serif;
                color: #666666;
                background-color: white;
                display: none; 
            }

            #instruction {
                height: 100%;
                text-align: center;
                font: 16pt sans-serif;
                color: #eeeeee;
                display: none;
            }

        </style>

    </head>
    <body>
        <div id="svpanel">
            <div id="streeview-canvas">Stree View Here</div>
            <div id="status">Enter your start and end addresses and click <b>Route</b></div>
            <div id="instruction"></div>
        </div>

        <div id="directions-panel"></div>
        <div id="debugmsg-panel"></div>
        <div id="map-canvas"></div>

        <table id="controls">
            <tr><td style="width: 30%;">
                    <div id="SEinput">
                        <div class="controls">
                            <span class="label">From</span>
                            <span class="input"><input id="start" size="30" value=""/></span>
                        </div>
                        <div class="controls">
                            <span class="label">To</span>
                            <span class="input"><input id="end" size="30" value=""/></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 1</span>
                            <span class="input"><input id="w1" size="30" value=""/></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 2</span>
                            <span class="input"><input id="w2" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 3</span>
                            <span class="input"><input id="w3" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 4</span>
                            <span class="input"><input id="w4" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 5</span>
                            <span class="input"><input id="w5" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 6</span>
                            <span class="input"><input id="w6" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 7</span>
                            <span class="input"><input id="w7" size="30" /></span>
                        </div>
                        <div class="controls">
                            <span class="label">WayPoint 8</span>
                            <span class="input"><input id="w8" size="30" /></span>
                        </div>
                        為什麼只能設8個點? 去問GOOGLE吧
                    </div>
                </td><td style="width: 30%; text-align:start; ">
                    <div id="buttons">
                        <input type="button" value="路徑規劃" id="route" onclick="calcRoute()" />
                        <input type="button" value="Drive" id="stopgo"  onclick="startDriving()"  />
                        <br>
                        <strong>行動方式: </strong>
                        <select id="mode" onchange="calcRoute();">
                            <option value="DRIVING">開車</option>
                            <option value="WALKING">走路</option>
                            <option value="BICYCLING">自行車</option>
                            <option value="TRANSIT">公車</option>
                        </select>
                        <br>
                        <strong>行進速度: </strong>
                        <select id="speed" onchange="setSpeed()">
                            <option value="0">Very Fast</option>
                            <option value="0.5">Fast</option>
                            <option value="1" SELECTED>Medium</option>
                            <option value="5">Slow</option>
                            <option value="10">Very Slow</option>
                        </select>
                        <br>
                        <strong>街景</strong>
                        <input type="button" value="放大" id="svzoom" onclick="SvMax()" />
                    </div>
                </td><td>
                    <div id="debugmsg">Debug MSG</div>
                </td></tr>
        </table>
    </body>
</html>

